package com.ruibang.glass.material.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruibang.glass.common.domain.GlobalUser;
import com.ruibang.glass.common.domain.file.FileBusiness;
import com.ruibang.glass.material.constant.MaterialErrorCode;
import com.ruibang.glass.material.domain.req.*;
import com.ruibang.glass.material.domain.resp.DecideResultResp;
import com.ruibang.glass.material.domain.resp.GlassBindResp;
import com.ruibang.glass.material.domain.resp.QualityManageDetailResp;
import com.ruibang.glass.material.domain.resp.external.ContentTypeStartTime;
import com.ruibang.glass.material.domain.resp.external.RackBindRecord;
import com.ruibang.glass.material.entity.MaterialContentLot;
import com.ruibang.glass.material.feign.FileApi;
import com.ruibang.glass.material.feign.QualityApi;
import com.ruibang.glass.material.mapper.MaterialContentLotMapper;
import com.ruibang.glass.material.service.MaterialContentLotService;
import com.teaming.cloud.framework2.common.constant.CommonConstant;
import com.teaming.cloud.framework2.common.exception.ServiceException;
import com.teaming.cloud.framework2.common.model.ResultBody;
import com.teaming.cloud.framework2.common.pojo.PageRequest;
import com.teaming.cloud.framework2.common.pojo.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * A型架和水平托盘容器绑定的批次号信息 服务实现类
 * </p>
 *
 * @author wujie
 * @since 2024-02-05
 */
@Service
public class MaterialContentLotServiceImpl extends ServiceImpl<MaterialContentLotMapper, MaterialContentLot> implements MaterialContentLotService {

    @Autowired
    private CommonService commonService;

    @Autowired
    private FileApi fileApi;

    @Autowired
    private QualityApi qualityApi;

    @Override
    public MaterialContentLot getLotByParams(MaterialContentLotReq reqVo) {
        return baseMapper.getLotByParams(reqVo);
    }

    @Override
    public MaterialContentLot getLotByContentCode(String contentCode) {
        return baseMapper.getLotByContentCode(contentCode);
    }

    @Override
    public List<ContentTypeStartTime> getLotTypeStartTime() {
        return baseMapper.getLotTypeStartTime();
    }

    /***
     * 同步冷端批次数据
     */
    @Override
    public void syncColdSideLotData(String startTime) {
        baseMapper.updateColdContentLot(startTime);
        List<RackBindRecord> records = baseMapper.querySLRackBindRecord(startTime);
        if (CollectionUtils.isNotEmpty(records)) {
            List<MaterialContentLot> materialContentLots = new ArrayList<>();
            records.stream().forEach(r -> {
                if (r != null) {
                    MaterialContentLot lot = new MaterialContentLot();
                    lot.setLotId(r.getId());
                    lot.setContentCode(r.getRackId());
                    lot.setBatchNumber(r.getRackUseBatch());
                    lot.setLineName(r.getProductionLineCode());
                    if (StringUtils.isNotBlank(r.getRackType()) && !"null".equals(r.getRackType())) {
                        lot.setPosition(r.getRackType());
                    }
                    lot.setNum(StringUtils.isEmpty(r.getRackBindNum()) ? 0 : Integer.parseInt(r.getRackBindNum()));
                    lot.setCreateTime(StringUtils.isEmpty(r.getCreateTime())
                            ? String.valueOf(Timestamp.valueOf(LocalDateTime.now()).getTime()) : r.getCreateTime());
                    lot.setResult(r.getSlZdjResult());
                    lot.setLevel(r.getSlZdjResult());
                    lot.setContentType(CommonConstant.TWO_STR);
                    materialContentLots.add(lot);
                }
            });
            baseMapper.insertBatch(materialContentLots);
        }
    }

    /***
     * 同步热端批次数据
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void syncHotSideLotData(String startTime) {
        baseMapper.updateHotContentLot(startTime);
        List<RackBindRecord> records = baseMapper.queryBCRackBindRecord(startTime);
        if (CollectionUtils.isNotEmpty(records)) {
            List<MaterialContentLot> materialContentLots = new ArrayList<>();
            records.stream().forEach(r -> {
                if (r != null) {
                    MaterialContentLot lot = new MaterialContentLot();
                    lot.setLotId(r.getId());
                    lot.setContentCode(r.getRackId());
                    lot.setBatchNumber(r.getRackUseBatch());
                    lot.setLineName(r.getProductionLineCode());
                    if (StringUtils.isNotBlank(r.getRackType()) && !"null".equals(r.getRackType())) {
                        lot.setPosition(r.getRackType());
                    }
                    lot.setNum(StringUtils.isEmpty(r.getRackBindNum()) ? 0 : Integer.parseInt(r.getRackBindNum()));
                    lot.setCreateTime(StringUtils.isEmpty(r.getCreateTime())
                            ? String.valueOf(Timestamp.valueOf(LocalDateTime.now()).getTime()) : r.getCreateTime());
                    lot.setContentType(CommonConstant.THREE_STR);
                    materialContentLots.add(lot);
                }
            });
            baseMapper.insertBatch(materialContentLots);
        }
    }

    @Override
    public PageResult<MaterialContentLot> queryPage(PageRequest<MaterialContentLotReq> pageRequest) {
        final MaterialContentLotReq param = pageRequest.getParam();
        final LambdaQueryWrapper<MaterialContentLot> lambda = new QueryWrapper<MaterialContentLot>().lambda();
        this.buildCondition(lambda, param);
        final IPage<MaterialContentLot> page = this.page(new Page<>(pageRequest.getPageNo(), pageRequest.getPageSize()), lambda);

        PageResult<MaterialContentLot> pr = new PageResult(page);
        return pr;
    }

    @Override
    public PageResult<QualityManageDetailResp> queryAppPage(PageRequest<MaterialContentLotReq> pageRequest) {
        final IPage<QualityManageDetailResp> page = new Page<>(pageRequest.getPageNo(), pageRequest.getPageSize());
        List<QualityManageDetailResp> lots = baseMapper.queryByContentCode(page, pageRequest.getParam().getContentCode());
        page.setRecords(lots);
        PageResult<QualityManageDetailResp> pr = new PageResult(page);
        return pr;
    }

    @Override
    public QualityManageDetailResp getContentDetail(String lotId) {
        return baseMapper.getContentDetail(lotId);
    }

    @Override
    public List<GlassBindResp> getGlassBindData(GlassBindReq glassBindReq) {
        List<GlassBindResp> bindRs = baseMapper.getGlassBindData(glassBindReq);
        if (CollectionUtils.isNotEmpty(bindRs)) {
            ResultBody<List<DecideResultResp>> resultBody = qualityApi.queryDecideResult(bindRs.stream().map(g -> g.getGlassCode()).collect(Collectors.toList()));
            if (resultBody != null && CollectionUtils.isNotEmpty(resultBody.getData())) {
                Map<String, List<DecideResultResp>> glassMap = resultBody.getData().stream().collect(Collectors.groupingBy(DecideResultResp::getGlassCode));
                Map<String, String> decideMap = new HashMap<>();
                glassMap.forEach((k, v) -> {
                    decideMap.put(k, CommonConstant.ZERO_STR);
                    if (CollectionUtils.isNotEmpty(v)) {
                        for (DecideResultResp dr : v) {
                            if (CommonConstant.ONE_STR.equals(dr.getDecide())) {
                                decideMap.put(k, CommonConstant.ONE_STR);
                                break;
                            }
                        }
                    }
                });
                for (int i = 0; i < bindRs.size(); i++) {
                    GlassBindResp bind = bindRs.get(i);
                    if (bind != null && StringUtils.isEmpty(bind.getDecide())) {
                        String decide = decideMap.get(bind.getGlassCode());
                        if (StringUtils.isBlank(decide)) {
                            if (i > 0) {
                                GlassBindResp bindFront = bindRs.get(i - 1);
                                String decideValue = bindFront.getDecide();
                                if (CommonConstant.ONE_STR.equals(decideValue)) {
                                    bind.setDecide(decideValue);
                                } else {
                                    bind.setDecide(CommonConstant.ZERO_STR);
                                    int m = i;
                                    while (m < bindRs.size()) {
                                        m++;
                                        GlassBindResp later = bindRs.get(m);
                                        String decideLater = decideMap.get(later.getGlassCode());
                                        if (StringUtils.isNotBlank(decideLater)) {
                                            bind.setDecide(decideLater);
                                            break;
                                        }
                                    }
                                }
                            } else if (i == 0) {
                                bind.setDecide(CommonConstant.ZERO_STR);
                            }
                        } else {
                            bind.setDecide(decide);
                        }
                    }
                }
            }
        }
        Collections.reverse(bindRs);
        return bindRs;
    }

    @Override
    public void unbind(UnbindReq unbindReq) {
        if (CollectionUtils.isNotEmpty(unbindReq.getGlassCodes())) {
            if (CollectionUtils.isEmpty(unbindReq.getSerialNumbers())) {
                throw new ServiceException(MaterialErrorCode.GLASS_UNCHECKED_MAX_SERIAL_NUMBER.getCode(), MaterialErrorCode.GLASS_UNCHECKED_MAX_SERIAL_NUMBER.getMsg());
            } else {
                Integer maxNo = baseMapper.getMaxSerialNumber(unbindReq.getBatchNumber());
                if (maxNo != null) {
                    boolean exist = unbindReq.getSerialNumbers().stream().anyMatch(m -> m.equals(maxNo));
                    if (!exist) {
                        throw new ServiceException(MaterialErrorCode.GLASS_UNCHECKED_MAX_SERIAL_NUMBER.getCode(), MaterialErrorCode.GLASS_UNCHECKED_MAX_SERIAL_NUMBER.getMsg());
                    }
                }
            }
            if (StringUtils.isBlank(unbindReq.getUnbindUser())) {
                GlobalUser user = commonService.getUser();
                unbindReq.setUnbindUser(user.getUserId());
            }
            unbindReq.setUnbindTime(LocalDateTime.now());
            unbindReq.setGlassCodes(unbindReq.getGlassCodes());
            baseMapper.unbinds(unbindReq);
        } else {
            if (StringUtils.isNotBlank(unbindReq.getLotId())) {
                List<String> glassCodes = baseMapper.getBindDataByLotId(unbindReq.getLotId());
                if (CollectionUtils.isNotEmpty(glassCodes)) {
                    if (StringUtils.isBlank(unbindReq.getUnbindUser())) {
                        GlobalUser user = commonService.getUser();
                        unbindReq.setUnbindUser(user.getUserId());
                    }
                    unbindReq.setUnbindTime(LocalDateTime.now());
                    unbindReq.setGlassCodes(glassCodes);
                    baseMapper.unbinds(unbindReq);
                }
            }
        }

    }

    @Override
    public void applyCheck(QualityCheckReq checkReq) {
        baseMapper.applyCheck(checkReq);
    }

    @Override
    public void checkQuality(QualityCheckReq checkReq) {
        if (CollectionUtils.isNotEmpty(checkReq.getFileIds())) {
            //更新文件对应业务Id
            FileBusiness fileBusiness = new FileBusiness();
            fileBusiness.setFileIds(checkReq.getFileIds());
            fileBusiness.setBusinessId(checkReq.getLotId());
            fileApi.updateBusinessById(fileBusiness);
        }
        if (CommonConstant.ONE_STR.equals(checkReq.getIsPass())) {
            checkReq.setInStatus(CommonConstant.FOUR_STR);
        }
        baseMapper.checkQuality(checkReq);
    }

    @Override
    public void changeQuality(QualityChangeReq changeReq) {
        baseMapper.changeQuality(changeReq);
    }

    @Override
    public void applyWarehouse(String lotId) {
        baseMapper.applyWarehouse(lotId);
    }


    /**
     * 构造查询条件
     *
     * @param lambda
     * @param param
     */
    private void buildCondition(LambdaQueryWrapper<MaterialContentLot> lambda, MaterialContentLotReq param) {
        if (null == param) return;
        if (!org.springframework.util.StringUtils.isEmpty(param.getLotId())) {
            lambda.eq(MaterialContentLot::getLotId, param.getLotId());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getContentCode())) {
            lambda.eq(MaterialContentLot::getContentCode, param.getContentCode());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getLotCode())) {
            lambda.eq(MaterialContentLot::getLotCode, param.getLotCode());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getBatchNumber())) {
            lambda.eq(MaterialContentLot::getBatchNumber, param.getBatchNumber());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getLineName())) {
            lambda.eq(MaterialContentLot::getLineName, param.getLineName());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getGlassCode())) {
            lambda.eq(MaterialContentLot::getGlassCode, param.getGlassCode());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getPosition())) {
            lambda.eq(MaterialContentLot::getPosition, param.getPosition());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getCurrentUsePosition())) {
            lambda.eq(MaterialContentLot::getCurrentUsePosition, param.getCurrentUsePosition());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getNum())) {
            lambda.eq(MaterialContentLot::getNum, param.getNum());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getModelLevel())) {
            lambda.eq(MaterialContentLot::getModelLevel, param.getModelLevel());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getLevel())) {
            lambda.eq(MaterialContentLot::getLevel, param.getLevel());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getLength())) {
            lambda.eq(MaterialContentLot::getLength, param.getLength());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getWide())) {
            lambda.eq(MaterialContentLot::getWide, param.getWide());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getThickness())) {
            lambda.eq(MaterialContentLot::getThickness, param.getThickness());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getInStatus())) {
            lambda.eq(MaterialContentLot::getInStatus, param.getInStatus());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getStatus())) {
            lambda.eq(MaterialContentLot::getStatus, param.getStatus());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getMesStatus())) {
            lambda.eq(MaterialContentLot::getMesStatus, param.getMesStatus());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getUpdateUser())) {
            lambda.eq(MaterialContentLot::getUpdateUser, param.getUpdateUser());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getContentType())) {
            lambda.eq(MaterialContentLot::getContentType, param.getContentType());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getResult())) {
            lambda.eq(MaterialContentLot::getResult, param.getResult());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getIsUnbind())) {
            lambda.eq(MaterialContentLot::getIsUnbind, param.getIsUnbind());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getMomNum())) {
            lambda.eq(MaterialContentLot::getMomNum, param.getMomNum());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getChangeLevelReason())) {
            lambda.eq(MaterialContentLot::getChangeLevelReason, param.getChangeLevelReason());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getChangeLevelUser())) {
            lambda.eq(MaterialContentLot::getChangeLevelUser, param.getChangeLevelUser());
        }
        if (!org.springframework.util.StringUtils.isEmpty(param.getUnqualifiedReason())) {
            lambda.eq(MaterialContentLot::getUnqualifiedReason, param.getUnqualifiedReason());
        }
        lambda.orderBy(true, false, MaterialContentLot::getLotId);
    }


}
